package com.egs.witzbackend.game;

import java.util.ArrayList;

import javax.jdo.JDOObjectNotFoundException;
import javax.jdo.PersistenceManager;
import javax.jdo.PersistenceManagerFactory;

import com.egs.witzbackend.domain.GameMatch;
import com.egs.witzbackend.domain.Move;
import com.egs.witzbackend.domain.Player;
import com.google.appengine.api.datastore.DatastoreService;
import com.google.appengine.api.datastore.DatastoreServiceFactory;
import com.google.appengine.api.datastore.Entity;
import com.google.appengine.api.datastore.Key;
import com.google.appengine.api.datastore.KeyFactory;
import com.google.appengine.api.datastore.PreparedQuery;
import com.google.appengine.api.datastore.Query;
import com.google.appengine.api.datastore.Text;

public class GameService {
	private PersistenceManagerFactory PMF;
	public GameService (PersistenceManagerFactory PMF) {
		this.PMF = PMF;
	}
	
	public GameMatch RegisterGameMatch(String gameId, Player player1, Player player2, String gameString) {
		PersistenceManager pm = PMF.getPersistenceManager();
		
		GameMatch gameMatch = new GameMatch(gameId, player1.getPlayerId(), player2.getPlayerId());
		if (gameString != null) {
			Text gameStringText = new Text(gameString);
			gameMatch.setGameString(gameStringText);
		}
		Key key = KeyFactory.createKey(GameMatch.class.getSimpleName(), "gameId:" + gameId + "&" + "p1:" + player1.getPlayerId() + "&" + "p2:" + player2.getPlayerId());
	    gameMatch.setKey(key);
		
	    GameMatch detached = null;
	    
		try {
            pm.makePersistent(gameMatch);
            detached = pm.detachCopy(gameMatch);
        } finally {
            pm.close();
        }
		
		return detached;
		
	}
	
	public void RegisterGameString(GameMatch gameMatch, String gameString) {
		PersistenceManager pm = PMF.getPersistenceManager();
		Text gameStringText = new Text(gameString);
		gameMatch.setGameString(gameStringText);
		
		try {
            pm.makePersistent(gameMatch);
        } finally {
            pm.close();
        }
	}
	
	public GameMatch GetGameMatch(String gameId, Player player1, Player player2) {
		PersistenceManager pm = PMF.getPersistenceManager();
		
		Key k = KeyFactory.createKey(GameMatch.class.getSimpleName(), "gameId:" + gameId + "&" + "p1:" + player1.getPlayerId() + "&" + "p2:" + player2.getPlayerId());
		
		GameMatch gameMatch = null;
		GameMatch detached = null;
		try {
			gameMatch = pm.getObjectById(GameMatch.class, k);
			detached = pm.detachCopy(gameMatch);
		} catch (JDOObjectNotFoundException e) {
			
		} finally {
            pm.close();
        }
		
		return detached;
	}
	
	public void DeleteGameMatch(GameMatch gameMatch) {
		PersistenceManager pm = PMF.getPersistenceManager();

		try {
			pm.deletePersistent(gameMatch);
		} catch (JDOObjectNotFoundException e) {
			
		} finally {
            pm.close();
        }
	}
	
	public Move GetMove(GameMatch gameMatch) {
		PersistenceManager pm = PMF.getPersistenceManager();
		
		Key k = KeyFactory.createKey(Move.class.getSimpleName(), "p1:" + gameMatch.getPlayer1Id() + "&" + "p2:" + gameMatch.getPlayer2Id());
		
		Move move = null;
		
		try {
			move = pm.getObjectById(Move.class, k);
		} catch (JDOObjectNotFoundException e) {
			
		}
		return move;
	}
	
	public void RegisterMove(GameMatch gameMatch, String playerId, String startX, String startY, String endX, String endY, String boardBeforeMove, String boardAfterMove, String hpP1BeforeMove, String hpP2BeforeMove, String hpP1AfterMove, String hpP2AfterMove) {
		PersistenceManager pm = PMF.getPersistenceManager();
		
		Key key = KeyFactory.createKey(Move.class.getSimpleName(), "p1:" + gameMatch.getPlayer1Id() + "&" + "p2:" + gameMatch.getPlayer2Id());
		
		Move move = null;
		
		try {
			move = pm.getObjectById(Move.class, key);
		} catch (JDOObjectNotFoundException e) {
			
		}
		
		if (move == null) {
			move = new Move(playerId, startX, startY, endX, endY, boardBeforeMove, boardAfterMove, hpP1BeforeMove, hpP2BeforeMove, hpP1AfterMove, hpP2AfterMove);
			move.setKey(key);
			
			try {
	            pm.makePersistent(move);
	        } finally {
	            pm.close();
	        }
		} else {
			move.setPlayerId(playerId);
			move.setStartX(startX);
			move.setStartY(startY);
			move.setEndX(endX);
			move.setEndY(endY);
			move.setBoardBeforeMove(boardBeforeMove);
			move.setBoardAfterMove(boardAfterMove);
			move.setHpP1BeforeMove(hpP1BeforeMove);
			move.setHpP2BeforeMove(hpP2BeforeMove);
			move.setHpP1AfterMove(hpP1AfterMove);
			move.setHpP2AfterMove(hpP2AfterMove);
			
			pm.close();
		}
	}
	
	public ArrayList<GameMatch> GetGameMatches(String gameId, Player player) {
		DatastoreService datastore = DatastoreServiceFactory.getDatastoreService();
		
		Query q = new Query("GameMatch");
		q.addFilter("gameId", Query.FilterOperator.EQUAL, gameId);
		q.addFilter("player1Id", Query.FilterOperator.EQUAL, player.getPlayerId());
		// PreparedQuery contains the methods for fetching query results
		// from the datastore
		PreparedQuery pq = datastore.prepare(q);
		ArrayList<GameMatch> gameMatches = new ArrayList<GameMatch>();
		for (Entity result : pq.asIterable()) {
			String player1Id = (String) result.getProperty("player1Id");
			String player2Id = (String) result.getProperty("player2Id");
			Text gameString = (Text) result.getProperty("gameString");
			GameMatch gameMatch = new GameMatch(gameId, player1Id, player2Id);
			gameMatch.setGameString(gameString);
			gameMatches.add(gameMatch);
		}
		
		q = new Query("GameMatch");
		q.addFilter("gameId", Query.FilterOperator.EQUAL, gameId);
		q.addFilter("player2Id", Query.FilterOperator.EQUAL, player.getPlayerId());
		// PreparedQuery contains the methods for fetching query results
		// from the datastore
		pq = datastore.prepare(q);
		for (Entity result : pq.asIterable()) {
			String player1Id = (String) result.getProperty("player1Id");
			String player2Id = (String) result.getProperty("player2Id");
			Text gameString = (Text) result.getProperty("gameString");
			GameMatch gameMatch = new GameMatch(gameId, player1Id, player2Id);
			gameMatch.setGameString(gameString);
			gameMatches.add(gameMatch);
		}
		
		return gameMatches;
	}
}
